package com.strato.serializer.xstream.v1_0_0;

import java.io.Writer;
import java.util.regex.Pattern;

import com.strato.classloader.v1_0_0.OverallBundleContextClassLoader;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;

public class DefaultXStreamCreator implements XStreamCreator {
	
	private static final String CDATA_FRONT = "<![CDATA[";
	private static final String CDATA_END = "]]>";
	private static final Pattern SPECIAL_CHAR_PATTERN = Pattern.compile("[&<>\"\']+?");
	
	public XStream createXStream() {
		XStream x = new XStream(new PureJavaReflectionProvider(),new CDataDriver());
		x.setClassLoader(OverallBundleContextClassLoader.getInstance());
		x.setMode(XStream.NO_REFERENCES);
		return x;
	}
	
	private static class CDataDriver extends DomDriver{
		public HierarchicalStreamWriter createWriter(Writer out) {
			return new PrettyPrintWriter(out){

				@Override
				protected void writeText(QuickWriter writer, String text) {
					String temp = text.trim();
					if(temp.startsWith(CDATA_FRONT) && temp.endsWith(CDATA_END)){
						writer.write(text);
					}else if(SPECIAL_CHAR_PATTERN.matcher(text).find()){
						StringBuffer stringBuffer = new StringBuffer();
						stringBuffer.append(CDATA_FRONT)
											.append(text)
											.append(CDATA_END);
						writer.write(stringBuffer.toString());
					}else{
						super.writeText(writer, text);
					}
				}
				
			};
		}
	}
	
}
